package com.gzc.just.play.last.war.sceneserver.damage;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import static org.junit.jupiter.api.Assertions.*;

/**
 * DamageType枚举的单元测试
 * 
 * @author AI Assistant
 * @version 1.0.0
 * @since 2025-11-25
 */
@DisplayName("伤害类型枚举测试")
class DamageTypeTest {

    @Test
    @DisplayName("测试枚举基本属性")
    void testEnumProperties() {
        // 测试物理伤害
        assertEquals(1, DamageType.PHYSICAL.getCode());
        assertEquals("物理伤害", DamageType.PHYSICAL.getName());
        assertEquals(1.0f, DamageType.PHYSICAL.getDamageMultiplier());
        
        // 测试魔法伤害
        assertEquals(2, DamageType.MAGICAL.getCode());
        assertEquals("魔法伤害", DamageType.MAGICAL.getName());
        assertEquals(1.0f, DamageType.MAGICAL.getDamageMultiplier());
        
        // 测试纯伤害
        assertEquals(3, DamageType.PURE.getCode());
        assertEquals("纯伤害", DamageType.PURE.getName());
        assertEquals(1.0f, DamageType.PURE.getDamageMultiplier());
        
        // 测试治疗
        assertEquals(4, DamageType.HEAL.getCode());
        assertEquals("治疗", DamageType.HEAL.getName());
        assertEquals(1.0f, DamageType.HEAL.getDamageMultiplier());
        
        // 测试真实伤害
        assertEquals(5, DamageType.TRUE_DAMAGE.getCode());
        assertEquals("真实伤害", DamageType.TRUE_DAMAGE.getName());
        assertEquals(1.0f, DamageType.TRUE_DAMAGE.getDamageMultiplier());
        
        // 测试毒伤
        assertEquals(6, DamageType.POISON.getCode());
        assertEquals("毒伤", DamageType.POISON.getName());
        assertEquals(1.0f, DamageType.POISON.getDamageMultiplier());
        
        // 测试灼烧
        assertEquals(7, DamageType.BURN.getCode());
        assertEquals("灼烧", DamageType.BURN.getName());
        assertEquals(1.0f, DamageType.BURN.getDamageMultiplier());
        
        // 测试流血
        assertEquals(8, DamageType.BLEED.getCode());
        assertEquals("流血", DamageType.BLEED.getName());
        assertEquals(1.0f, DamageType.BLEED.getDamageMultiplier());
        
        // 测试未知伤害
        assertEquals(0, DamageType.UNKNOWN.getCode());
        assertEquals("未知伤害", DamageType.UNKNOWN.getName());
        assertEquals(1.0f, DamageType.UNKNOWN.getDamageMultiplier());
    }

    @Test
    @DisplayName("测试fromCode方法")
    void testFromCode() {
        // 测试所有有效编码
        assertEquals(DamageType.PHYSICAL, DamageType.fromCode(1));
        assertEquals(DamageType.MAGICAL, DamageType.fromCode(2));
        assertEquals(DamageType.PURE, DamageType.fromCode(3));
        assertEquals(DamageType.HEAL, DamageType.fromCode(4));
        assertEquals(DamageType.TRUE_DAMAGE, DamageType.fromCode(5));
        assertEquals(DamageType.POISON, DamageType.fromCode(6));
        assertEquals(DamageType.BURN, DamageType.fromCode(7));
        assertEquals(DamageType.BLEED, DamageType.fromCode(8));
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(0));
        
        // 测试无效编码
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(-1));
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(9));
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(100));
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(Integer.MAX_VALUE));
    }

    @ParameterizedTest
    @EnumSource(DamageType.class)
    @DisplayName("测试canBeDefended方法")
    void testCanBeDefended(DamageType damageType) {
        switch (damageType) {
            case PHYSICAL:
                assertTrue(damageType.canBeDefended());
                break;
            case MAGICAL:
                assertTrue(damageType.canBeDefended());
                break;
            case PURE:
            case HEAL:
            case TRUE_DAMAGE:
            case POISON:
            case BURN:
            case BLEED:
            case UNKNOWN:
                assertFalse(damageType.canBeDefended());
                break;
        }
    }

    @ParameterizedTest
    @EnumSource(DamageType.class)
    @DisplayName("测试isDOT方法")
    void testIsDOT(DamageType damageType) {
        switch (damageType) {
            case POISON:
            case BURN:
            case BLEED:
                assertTrue(damageType.isDOT());
                break;
            case PHYSICAL:
            case MAGICAL:
            case PURE:
            case HEAL:
            case TRUE_DAMAGE:
            case UNKNOWN:
                assertFalse(damageType.isDOT());
                break;
        }
    }

    @Test
    @DisplayName("测试特定伤害类型属性")
    void testSpecificDamageTypeProperties() {
        // 测试可以被防御的伤害类型
        assertTrue(DamageType.PHYSICAL.canBeDefended());
        assertTrue(DamageType.MAGICAL.canBeDefended());
        
        // 测试无法被防御的伤害类型
        assertFalse(DamageType.PURE.canBeDefended());
        assertFalse(DamageType.HEAL.canBeDefended());
        assertFalse(DamageType.TRUE_DAMAGE.canBeDefended());
        
        // 测试持续伤害类型
        assertTrue(DamageType.POISON.isDOT());
        assertTrue(DamageType.BURN.isDOT());
        assertTrue(DamageType.BLEED.isDOT());
        
        // 测试非持续伤害类型
        assertFalse(DamageType.PHYSICAL.isDOT());
        assertFalse(DamageType.MAGICAL.isDOT());
        assertFalse(DamageType.PURE.isDOT());
        assertFalse(DamageType.HEAL.isDOT());
        assertFalse(DamageType.TRUE_DAMAGE.isDOT());
    }

    @Test
    @DisplayName("测试枚举值的完整性")
    void testEnumCompleteness() {
        // 验证枚举值的数量
        DamageType[] values = DamageType.values();
        assertEquals(9, values.length, "应该有9个枚举值");
        
        // 验证所有值都不为null
        for (DamageType type : values) {
            assertNotNull(type);
        }
        
        // 验证所有code值都是唯一的（除了UNKNOWN都是唯一的）
        for (int i = 0; i < values.length; i++) {
            for (int j = i + 1; j < values.length; j++) {
                if (values[i] != DamageType.UNKNOWN && values[j] != DamageType.UNKNOWN) {
                    assertNotEquals(values[i].getCode(), values[j].getCode());
                }
            }
        }
    }

    @Test
    @DisplayName("测试toString方法")
    void testToString() {
        assertEquals("PHYSICAL", DamageType.PHYSICAL.toString());
        assertEquals("MAGICAL", DamageType.MAGICAL.toString());
        assertEquals("PURE", DamageType.PURE.toString());
        assertEquals("HEAL", DamageType.HEAL.toString());
        assertEquals("TRUE_DAMAGE", DamageType.TRUE_DAMAGE.toString());
        assertEquals("POISON", DamageType.POISON.toString());
        assertEquals("BURN", DamageType.BURN.toString());
        assertEquals("BLEED", DamageType.BLEED.toString());
        assertEquals("UNKNOWN", DamageType.UNKNOWN.toString());
    }

    @Test
    @DisplayName("测试valueOf方法")
    void testValueOf() {
        // 测试所有有效枚举名称
        assertEquals(DamageType.PHYSICAL, DamageType.valueOf("PHYSICAL"));
        assertEquals(DamageType.MAGICAL, DamageType.valueOf("MAGICAL"));
        assertEquals(DamageType.PURE, DamageType.valueOf("PURE"));
        assertEquals(DamageType.HEAL, DamageType.valueOf("HEAL"));
        assertEquals(DamageType.TRUE_DAMAGE, DamageType.valueOf("TRUE_DAMAGE"));
        assertEquals(DamageType.POISON, DamageType.valueOf("POISON"));
        assertEquals(DamageType.BURN, DamageType.valueOf("BURN"));
        assertEquals(DamageType.BLEED, DamageType.valueOf("BLEED"));
        assertEquals(DamageType.UNKNOWN, DamageType.valueOf("UNKNOWN"));
    }

    @Test
    @DisplayName("测试枚举比较")
    void testEnumComparison() {
        // 同一值比较
        assertEquals(DamageType.PHYSICAL, DamageType.PHYSICAL);
        
        // 不同值比较
        assertNotEquals(DamageType.PHYSICAL, DamageType.MAGICAL);
        assertNotEquals(DamageType.PURE, DamageType.TRUE_DAMAGE);
        
        // equals方法与==操作符一致性
        assertTrue(DamageType.PHYSICAL == DamageType.PHYSICAL);
        assertFalse(DamageType.PHYSICAL == DamageType.MAGICAL);
    }

    @Test
    @DisplayName("测试hashCode方法")
    void testHashCode() {
        // 同一枚举值的hashCode应该相同
        assertEquals(DamageType.PHYSICAL.hashCode(), DamageType.PHYSICAL.hashCode());
        assertEquals(DamageType.MAGICAL.hashCode(), DamageType.MAGICAL.hashCode());
        
        // 不同枚举值的hashCode应该不同
        assertNotEquals(DamageType.PHYSICAL.hashCode(), DamageType.MAGICAL.hashCode());
        assertNotEquals(DamageType.PURE.hashCode(), DamageType.HEAL.hashCode());
        
        // 所有枚举值的hashCode都应该是一致的（对于相同枚举值）
        for (int i = 0; i < 3; i++) {
            assertEquals(DamageType.PHYSICAL.hashCode(), DamageType.PHYSICAL.hashCode());
        }
    }

    @Test
    @DisplayName("测试枚值的顺序")
    void testEnumOrder() {
        DamageType[] values = DamageType.values();
        
        // 验证枚举值按声明顺序排列（根据实际代码）
        assertEquals(DamageType.PHYSICAL, values[0]);
        assertEquals(DamageType.MAGICAL, values[1]);
        assertEquals(DamageType.PURE, values[2]);
        assertEquals(DamageType.HEAL, values[3]);
        assertEquals(DamageType.TRUE_DAMAGE, values[4]);
        assertEquals(DamageType.POISON, values[5]);
        assertEquals(DamageType.BURN, values[6]);
        assertEquals(DamageType.BLEED, values[7]);
        assertEquals(DamageType.UNKNOWN, values[8]);
    }

    @Test
    @DisplayName("测试特殊伤害类型属性")
    void testSpecialDamageTypes() {
        // 测试治疗
        assertFalse(DamageType.HEAL.canBeDefended());
        assertFalse(DamageType.HEAL.isDOT());
        assertEquals(4, DamageType.HEAL.getCode());
        assertEquals("治疗", DamageType.HEAL.getName());
        
        // 测试真实伤害
        assertFalse(DamageType.TRUE_DAMAGE.canBeDefended());
        assertFalse(DamageType.TRUE_DAMAGE.isDOT());
        assertEquals(5, DamageType.TRUE_DAMAGE.getCode());
        assertEquals("真实伤害", DamageType.TRUE_DAMAGE.getName());
        
        // 测试纯伤害
        assertFalse(DamageType.PURE.canBeDefended());
        assertFalse(DamageType.PURE.isDOT());
        assertEquals(3, DamageType.PURE.getCode());
        assertEquals("纯伤害", DamageType.PURE.getName());
        
        // 测试未知伤害
        assertFalse(DamageType.UNKNOWN.canBeDefended());
        assertFalse(DamageType.UNKNOWN.isDOT());
        assertEquals(0, DamageType.UNKNOWN.getCode());
        assertEquals("未知伤害", DamageType.UNKNOWN.getName());
    }

    @Test
    @DisplayName("测试边界值")
    void testEdgeCases() {
        // 测试fromCode的边界值
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(Integer.MIN_VALUE));
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(Integer.MAX_VALUE));
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(-100));
        assertEquals(DamageType.UNKNOWN, DamageType.fromCode(100));
    }
}